home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 2: CDPD 1 / Almathera Ten on Ten - Disc 2: CDPD 1.iso / pd / 351-375 / 351 / pdc / pdcsrc.lzh / PDC / OutCode.c < prev    next >
C/C++ Source or Header  |  1990-04-06  |  23KB  |  1,108 lines

  1.  
  2. /* PDC Compiler - A Freely Distributable C Compiler for the Amiga
  3.  *                Based upon prior work by Matthew Brandt and Jeff Lydiatt.
  4.  *
  5.  * PDC Compiler release 3.3 Copyright (C) 1989 Paul Petersen and Lionel Hummel.
  6.  * PDC Software Distribution (C) 1989 Lionel Hummel and Paul Petersen.
  7.  *
  8.  * This code is freely redistributable upon the conditions that this 
  9.  * notice remains intact and that modified versions of this file not be 
  10.  * distributed as part of the PDC Software Distribution without the express
  11.  * consent of the copyright holders.
  12.  *
  13.  *------------------------------------------------------------------
  14.  *
  15.  * $Log:    OutCode.c,v $
  16.  * Revision 3.33  90/04/05  23:12:38  lionel
  17.  * Improved data and literal output code, fixed some parameter type probs.
  18.  * 
  19.  * Revision 3.32  90/02/03  16:25:06  lionel
  20.  * None
  21.  * 
  22.  *------------------------------------------------------------------
  23.  */
  24.  
  25. /*
  26.  * Outcode.c
  27.  * 
  28.  * Generates the actual assembly text from the code generator's directions.
  29.  */
  30.  
  31. #include    <stdio.h>
  32. #include    "C.h"
  33. #include    "Expr.h"
  34. #include    "Gen.h"
  35. #include    "Cglbdec.h"
  36.  
  37. extern char    *litlate();
  38. extern char    *xalloc();
  39.  
  40. void    put_mask(), nl(), cseg();
  41.  
  42. enum e_gt {
  43.     nogen, bytegen, wordgen, longgen, singlegen, doublegen
  44. };
  45.  
  46. enum e_sg {
  47.     noseg, codeseg, dataseg, bssseg
  48. };
  49.  
  50. union double_int {
  51.     double          dval;
  52.     float           fval;
  53.     int             ival[2];
  54. };
  55.  
  56. /* variable initialization     */
  57.  
  58. enum e_gt       gentype = nogen;
  59. enum e_sg       curseg = noseg;
  60. int             outcol = 0;
  61.  
  62. char *areg_format = "A%d";
  63. char *dreg_format = "D%d";
  64.  
  65. static int      opl_len = 0;
  66.  
  67. struct oplst {
  68.     char           *s;
  69.     enum e_op       ov;
  70. };
  71.  
  72. struct oplst    opl[] = {
  73.     {"abcd", op_abcd},
  74.     {"add", op_add},
  75.     {"add", op_adda},
  76.     {"add", op_addi},
  77.     {"addq", op_addq},
  78.     {"add", op_addx},
  79.     {"and", op_and},
  80.     {"andi", op_andi},
  81.     {"asl", op_asl},
  82.     {"???", op_asm},
  83.     {"asr", op_asr},
  84.     {"bcc", op_bcc},
  85.     {"bchg", op_bchg},
  86.     {"bclr", op_bclr},
  87.     {"bcs", op_bcs},
  88.     {"beq", op_beq},
  89.     {"bge", op_bge},
  90.     {"bgt", op_bgt},
  91.     {"bhi", op_bhi},
  92.     {"ble", op_ble},
  93.     {"bls", op_bls},
  94.     {"blt", op_blt},
  95.     {"bmi", op_bmi},
  96.     {"bne", op_bne},
  97.     {"bpl", op_bpl},
  98.     {"bra", op_bra},
  99.     {"bset", op_bset},
  100.     {"bsr", op_bsr},
  101.     {"btst", op_btst},
  102.     {"bvc", op_bvc},
  103.     {"bvs", op_bvs},
  104.     {"chk", op_chk},
  105.     {"clr", op_clr},
  106.     {"cmp", op_cmp},
  107.     {"cmp", op_cmpa},
  108.     {"cmp", op_cmpi},
  109.     {"cmp", op_cmpm},
  110.     {";;;", op_comment},
  111.     {"dbcc", op_dbcc},
  112.     {"dbcs", op_dbcs},
  113.     {"dbeq", op_dbeq},
  114.     {"dbf", op_dbf},
  115.     {"dbge", op_dbge},
  116.     {"dbgt", op_dbgt},
  117.     {"dbhi", op_dbhi},
  118.     {"dble", op_dble},
  119.     {"dbls", op_dbls},
  120.     {"dbmi", op_dbmi},
  121.     {"dbne", op_dbne},
  122.     {"dbpl", op_dbpl},
  123.     {"dbra", op_dbra},
  124.     {"dbt", op_dbt},
  125.     {"dbvc", op_dbvc},
  126.     {"dbvs", op_dbvs},
  127.     {"dc", op_dc},
  128.     {"divs", op_divs},
  129.     {"divu", op_divu},
  130.     {"eor", op_eor},
  131.     {"eori", op_eori},
  132.     {"exg", op_exg},
  133.     {"ext", op_ext},
  134.     {"???", op_fadd},
  135.     {"???", op_fdiv},
  136.     {"???", op_fmod},
  137.     {"???", op_fmove},
  138.     {"???", op_fmul},
  139.     {"???", op_fneg},
  140.     {"???", op_fsub},
  141.     {"jmp", op_jmp},
  142.     {"jsr", op_jsr},
  143.     {"???", op_label},
  144.     {"lea", op_lea},
  145.     {"link", op_link},
  146.     {"lsl", op_lsl},
  147.     {"lsr", op_lsr},
  148.     {"???", op_mods},
  149.     {"???", op_modu},
  150.     {"move", op_move},
  151.     {"move", op_movea},
  152.     {"movem", op_movem},
  153.     {"movep", op_movep},
  154.     {"moveq", op_moveq},
  155.     {"muls", op_muls},
  156.     {"mulu", op_mulu},
  157.     {"nbcd", op_nbcd},
  158.     {"neg", op_neg},
  159.     {"negx", op_negx},
  160.     {"nop", op_nop},
  161.     {"not", op_not},
  162.     {"or", op_or},
  163.     {"ori", op_ori},
  164.     {"pea", op_pea},
  165.     {"reset", op_reset},
  166.     {"rol", op_rol},
  167.     {"ror", op_ror},
  168.     {"roxl", op_roxl},
  169.     {"roxr", op_roxr},
  170.     {"rte", op_rte},
  171.     {"rtr", op_rtr},
  172.     {"rts", op_rts},
  173.     {"sbcd", op_sbcd},
  174.     {"scc", op_scc},
  175.     {"scs", op_scs},
  176.     {"seq", op_seq},
  177.     {"sf", op_sf},
  178.     {"sge", op_sge},
  179.     {"sgt", op_sgt},
  180.     {"shi", op_shi},
  181.     {"sle", op_sle},
  182.     {"sls", op_sls},
  183.     {"slt", op_slt},
  184.     {"smi", op_smi},
  185.     {"sne", op_sne},
  186.     {"spl", op_spl},
  187.     {"st", op_st},
  188.     {"stabn", op_stabn},
  189.     {"stabs", op_stabs},
  190.     {"stop", op_stop},
  191.     {"sub", op_sub},
  192.     {"sub", op_suba},
  193.     {"sub", op_subi},
  194.     {"subq", op_subq},
  195.     {"sub", op_subx},
  196.     {"svc", op_svc},
  197.     {"svs", op_svs},
  198.     {"swap", op_swap},
  199.     {"tas", op_tas},
  200.     {"trap", op_trap},
  201.     {"trapv", op_trapv},
  202.     {"tst", op_tst},
  203.     {"unlk", op_unlk},
  204.     {(char *) 0, (enum e_op) 0}
  205. };
  206.  
  207. static char     buffer[64];
  208.  
  209. char           *
  210. itoa(x)
  211.     int             x;
  212. {
  213.     char           *ptr;
  214.     int             d, negative;
  215.  
  216.     ptr = &buffer[sizeof(buffer) - 1];
  217.     *ptr = '\0';
  218.  
  219.     if (x == 0x80000000)    /* The number where x = -x */
  220.         return ("-2147483648");
  221.  
  222.     negative = 0;
  223.     if (x < 0) {
  224.         negative = 1;
  225.         x = -x;
  226.     }
  227.  
  228.     do {
  229.         d = x % 10;
  230.         if (d < 0 || d > 9) {
  231.             fprintf(stderr, "DIAG -- itoa has a problem\n");
  232.             return (ptr);
  233.         }
  234.         x = x / 10;
  235.         *(--ptr) = '0' + d;
  236.     } while (x > 0);
  237.  
  238.     if (negative)
  239.         *(--ptr) = '-';
  240.     return (ptr);
  241. }
  242.  
  243. void
  244. putsingle(d)
  245.     double          d;
  246. {
  247.     union double_int temp;
  248.  
  249.     temp.fval = d;
  250.     fprintf( output, "%d", temp.ival[0] );
  251. }
  252.  
  253. void
  254. putdouble(d)
  255.     double          d;
  256. {
  257.     union double_int temp;
  258.  
  259.     temp.dval = d;
  260.     fprintf( output, "%d,%d", temp.ival[0], temp.ival[1] );
  261. }
  262.  
  263. void
  264. putareg(reg)
  265.     int             reg;
  266. {
  267.     fprintf(output, "A%d", reg );
  268. }
  269.  
  270. void
  271. putdreg(reg)
  272.     int             reg;
  273. {
  274.     fprintf(output, "D%d", reg );
  275. }
  276.  
  277. int
  278. sortopl()
  279. {
  280.     struct oplst   *p1, *p2, temp;
  281.     int             changed = 0;
  282.  
  283.     p1 = opl;
  284.     for (p2 = p1 + 1; p2->s != NULL; p1++, p2++) {
  285.         if ((int) p1->ov > (int) p2->ov) {
  286.             changed = 1;
  287.             temp = *p1;
  288.             *p1 = *p2;
  289.             *p2 = temp;
  290.         }
  291.     }
  292.     return changed;
  293. }
  294.  
  295. void
  296. putop(op, len)
  297.     enum e_op       op;
  298.     int             len;
  299. {
  300.     int             low, high, mid;
  301.     struct oplst   *ptr;
  302.     char           *lenstr;
  303.  
  304.     if (opl_len == 0) {
  305.         for (ptr = opl; ptr->s != NULL; ptr++)
  306.             ++opl_len;
  307.         while (sortopl());
  308.     }
  309.  
  310.     low = 0;
  311.     high = opl_len - 1;
  312.  
  313.     do {
  314.         mid = (low + high) / 2;
  315.         ptr = &opl[mid];
  316.  
  317.         if (ptr->ov == op) {
  318.             switch (len) {
  319.             case 0:
  320.                 lenstr = "";
  321.                 break;      /* no length field */
  322.             case 1:
  323.                 lenstr = ".b";
  324.                 break;
  325.             case 2:
  326.                 lenstr = ".w";
  327.                 break;
  328.             case 4:
  329.                 lenstr = ".l";
  330.                 break;
  331.             case 8:
  332.                 lenstr = ".f";
  333.                 break;
  334.             default:
  335.                 lenstr = ".x";
  336.                 fprintf( stderr, "DIAG -- illegal length field.\n" );
  337.                 break;
  338.             }
  339.             fprintf( output, "\t%s%s", ptr->s, lenstr );
  340.             return;
  341.         }
  342.         else {
  343.             if ((int) op > (int) ptr->ov)
  344.                 low = mid + 1;
  345.             else
  346.                 high = mid - 1;
  347.         }
  348.     } while (low <= high);
  349.  
  350.     fprintf( stderr, "DIAG -- illegal opcode.\n" );
  351. }
  352.  
  353. /*
  354.  * put a constant to the output file.
  355.  */
  356.  
  357. void
  358. putconst(offset)
  359.     struct enode   *offset;
  360. {
  361.     if (offset == NULL) {
  362.         fprintf( stderr, "DIAG -- NULL argument to putconst.\n" );
  363.         return;
  364.     }
  365.     switch (offset->nodetype) {
  366.     case en_autocon:
  367.         fprintf(output, "%d(A%d)", offset->v.i, Options.Frame);
  368.         break;
  369.     case en_icon:
  370.         fprintf(output, "%d", offset->v.i);
  371.         break;
  372.     case en_fcon:
  373.         putdouble(offset->v.f);
  374.         break;
  375.     case en_labcon:
  376.         fprintf( output, "L%d", offset->v.i);
  377.         break;
  378.     case en_nacon:
  379.         fprintf( output, "_%s", offset->v.p[0] );
  380.         break;
  381.     case en_intrlab:
  382.         fprintf( output, "%s", offset->v.p[0] );
  383.         break;
  384.     case en_add:
  385.         putconst(offset->v.p[0]);
  386.         fprintf( output, "+" );
  387.         putconst(offset->v.p[1]);
  388.         break;
  389.     case en_sub:
  390.         putconst(offset->v.p[0]);
  391.         fprintf( output, "-" );
  392.         putconst(offset->v.p[1]);
  393.         break;
  394.     case en_uminus:
  395.         fprintf( output, "-" );
  396.         putconst(offset->v.p[0]);
  397.         break;
  398.     default:
  399.         fprintf( stderr, "DIAG -- illegal constant node (%d)\n", 
  400.                          offset->nodetype );
  401.         break;
  402.     }
  403. }
  404.  
  405. void
  406. putamode(ap)
  407.  
  408. /*
  409.  * output a general addressing mode.
  410.  */
  411.     struct amode   *ap;
  412. {
  413.     if (ap == NULL) {
  414.         fprintf( stderr, "DIAG -- NULL argument to putamode.\n" );
  415.         return;
  416.     }
  417.     switch (ap->mode) {
  418.     case am_immed:
  419.         fprintf( output, "#" );
  420.         putconst(ap->offset);
  421.         break;
  422.     case am_direct:
  423.         putconst(ap->offset);
  424.         break;
  425.     case am_areg:
  426.         fprintf( output, areg_format, ap->preg);
  427.         break;
  428.     case am_dreg:
  429.         fprintf( output, dreg_format, ap->preg);
  430.         break;
  431.     case am_freg:
  432.         fprintf( output, dreg_format, (enum e_am) 0);
  433.         break;
  434.     case am_ind:
  435.         fprintf( output, "(A%d)", ap->preg);
  436.         break;
  437.     case am_ainc:
  438.         fprintf( output, "(A%d)+", ap->preg);
  439.         break;
  440.     case am_adec:
  441.         fprintf( output, "-(A%d)", ap->preg);
  442.         break;
  443.     case am_indx:
  444.         putconst(ap->offset);
  445.         fprintf( output, "(A%d)", ap->preg);
  446.         break;
  447.     case am_xpc:
  448.         putconst(ap->offset);
  449.         fprintf( output, "(A%d,pc)", ap->preg);
  450.         break;
  451.     case am_indx2:
  452.         putconst(ap->offset);
  453.         fprintf( output, "(A%d,D%d.l)", ap->preg, ap->sreg);
  454.         break;
  455.     case am_indx3:
  456.         putconst(ap->offset);
  457.         fprintf( output, "(A%d,A%d.l)", ap->preg, ap->sreg );
  458.         break;
  459.     case am_mask:
  460.         put_mask((long) (ap->offset));
  461.         break;
  462.     default:
  463.         fprintf( stderr, "DIAG -- illegal address mode.\n" );
  464.         fprintf( output, "<DIAG -- illegal address mode.>" );
  465.         break;
  466.     }
  467. }
  468.  
  469. void
  470. put_code(op, len, aps, apd)
  471.  
  472. /*
  473.  * output a generic instruction.
  474.  */
  475.     struct amode   *aps, *apd;
  476.     enum e_op       op;
  477.     int             len;
  478. {
  479.     char           *comment;
  480.     struct dnode   *dp;
  481.     char            lench;
  482.  
  483.     switch (op) {
  484.     case op_comment:
  485.         comment = aps->offset->v.sp;
  486.         nl();
  487.         fprintf( output, ";;;\t%s\n", comment );
  488.         return;
  489.     case op_asm:
  490.         comment = aps->offset->v.sp;
  491.         nl();
  492.         fprintf( output, "%s\n", comment );
  493.         return;
  494.     case op_stabn:
  495.         dp = aps->offset->v.dp;
  496.         fprintf( output, "\tSTABN\t%d,0,%d,", dp->tag, dp->nest );
  497.         putconst(dp->ref);
  498.         fprintf( output, "\n" );
  499.         return;
  500.     case op_stabs:
  501.         dp = aps->offset->v.dp;
  502.         if (dp->ref->nodetype == en_autocon || dp->ref->nodetype == en_tempref)
  503.             dp->ref->nodetype = en_icon;
  504.         comment = dp->sp;
  505.         do {
  506.             fprintf( output, "\tSTABS\t\"" );
  507.  
  508.             while (*comment && (*comment != '\\')) {
  509.                 fputc(*comment, output);
  510.                 comment++;
  511.                 if (*comment == '\0' && dp->next != NULL) {
  512.                     dp = dp->next;
  513.                     comment = dp->sp;
  514.                 }
  515.             }
  516.  
  517.             if (*comment) {
  518.                 fputc(*comment++, output);
  519.                 fputc(*comment++, output);
  520.             }
  521.  
  522.             fprintf( output, "\",%d,0,%d,", dp->tag, dp->nest );
  523.             putconst(dp->ref);
  524.             fprintf( output, "\n" );
  525.  
  526.             if (*comment == '\0' && dp->next != NULL) {
  527.                 dp = dp->next;
  528.                 comment = dp->sp;
  529.             }
  530.         } while (*comment);
  531.         return;
  532.     case op_dc:
  533.         switch (len) {
  534.         case 1:
  535.             lench = 'b';
  536.             break;
  537.         case 2:
  538.             lench = 'w';
  539.             break;
  540.         case 4:
  541.             lench = 'l';
  542.             break;
  543.         case 8:
  544.             lench = 'l';
  545.         }
  546.         fprintf( output, "\tDC.%c", lench );
  547.         break;
  548.     default:
  549.         putop(op, len);
  550.         break;
  551.     }
  552.  
  553.     if (aps != NULL) {
  554.         fprintf( output, "\t" );
  555.         if (op == op_cmp || op == op_cmpi)
  556.             putamode(apd);
  557.         else
  558.             putamode(aps);
  559.         if (apd != NULL) {
  560.             fprintf( output, "," );
  561.             if (op == op_cmp || op == op_cmpi)
  562.                 putamode(aps);
  563.             else
  564.                 putamode(apd);
  565.         }
  566.     }
  567.     fprintf( output, "\n" );
  568. }
  569.  
  570. void
  571. startRange(bit)
  572.     int    bit;
  573. {
  574.     register int bit_mod8 = bit % 8;
  575.  
  576.     if (bit <= 7)
  577.         fprintf( output, dreg_format, bit_mod8);
  578.     else
  579.         fprintf( output, areg_format, bit_mod8);
  580. }
  581.  
  582. void
  583. endRange(first, bit)
  584.     int    first, bit;
  585. {
  586.     if (first <= 7 && bit > 7) {
  587.         endRange(first, 7);
  588.         fprintf( output, "/" );
  589.         startRange(8);
  590.         first = 8;
  591.     }
  592.     if (bit > first) {
  593.         fprintf( output, "-" );
  594.         startRange(bit);
  595.     }
  596. }
  597.  
  598. void
  599. put_mask(mask1)
  600.  
  601. /*
  602.  * generate a register mask for restore and save.
  603.  */
  604.     long            mask1;
  605. {
  606.     int             mask;
  607.     int             bit;
  608.     int             inrange;
  609.     int             some;
  610.  
  611.     mask = mask1;
  612.     inrange = -1;
  613.     some = 0;
  614.  
  615.     for (bit = 0; bit <= 15; ++bit) {
  616.         if ((mask >> bit) & 1) {
  617.             if (inrange < 0) {
  618.                 if (some)
  619.                     fprintf( output, "/" );
  620.                 startRange(bit);
  621.                 some = 1;
  622.                 inrange = bit;
  623.             }
  624.         }
  625.         else if (inrange >= 0) {
  626.             endRange(inrange, bit - 1);
  627.             inrange = -1;   /* was -= 1 PMP */
  628.         }
  629.     }
  630.     if (inrange >= 0)
  631.         endRange(inrange, 15);
  632. }
  633.  
  634. void
  635. putreg(r)
  636.  
  637. /*
  638.  * generate a register name from a tempref number.
  639.  */
  640.     int             r;
  641. {
  642.     if (r < 8)
  643.         putdreg(r);
  644.     else
  645.         putareg(r - 8);
  646. }
  647.  
  648. void
  649. gen_strlab(s)
  650.  
  651. /*
  652.  * generate a named label.
  653.  */
  654.     char           *s;
  655. {
  656.     fprintf( output, "_%s:\n", s );
  657. }
  658.  
  659. void
  660. put_label(lab)
  661.  
  662. /*
  663.  * output a compiler generated label.
  664.  */
  665.     long            lab;
  666. {
  667.     fprintf( output, "L%d\n", lab);
  668. }
  669.  
  670. void
  671. genbyte(val)
  672.     int             val;
  673. {
  674.     if (gentype == bytegen && outcol < 60) {
  675.         fprintf( output, ",%d", val & 0x00ff);
  676.         outcol += 4;
  677.     }
  678.     else {
  679.         nl();
  680.         fprintf( output, "\tDC.b\t%d", val & 0x00ff);
  681.         gentype = bytegen;
  682.         outcol = 19;
  683.     }
  684. }
  685.  
  686. void
  687. genword(val)
  688.     long            val;
  689. {
  690.     if (gentype == wordgen && outcol < 58) {
  691.         fprintf( output, ",%d", val & 0x0ffff);
  692.         outcol += 6;
  693.     }
  694.     else {
  695.         nl();
  696.         fprintf( output, "\tDC.w\t%d", val & 0x0ffff);
  697.         gentype = wordgen;
  698.         outcol = 21;
  699.     }
  700. }
  701.  
  702. void
  703. genlong(val)
  704.     long            val;
  705. {
  706.     if (gentype == longgen && outcol < 56) {
  707.         fprintf( output, ",%d", val );
  708.         outcol += 10;
  709.     }
  710.     else {
  711.         nl();
  712.         fprintf( output, "\tDC.l\t%d", val );
  713.         gentype = longgen;
  714.         outcol = 25;
  715.     }
  716. }
  717.  
  718. void
  719. gensingle(val)
  720.     double          val;
  721. {
  722.     if (gentype == singlegen && outcol < 56) {
  723.         fprintf( output, "," );
  724.         putsingle(val);
  725.         outcol += 10;
  726.     }
  727.     else {
  728.         nl();
  729.         fprintf( output, "\tDC.l\t" );
  730.         putsingle(val);
  731.         gentype = singlegen;
  732.         outcol = 35;
  733.     }
  734. }
  735.  
  736. void
  737. gendouble(val)
  738.     double          val;
  739. {
  740.     if (gentype == doublegen && outcol < 56) {
  741.         fprintf( output, "," );
  742.         putdouble(val);
  743.         outcol += 20;
  744.     }
  745.     else {
  746.         nl();
  747.         fprintf( output, "\tDC.l\t" );
  748.         putdouble(val);
  749.         gentype = doublegen;
  750.         outcol = 45;
  751.     }
  752. }
  753.  
  754. void
  755. genref(sp, offset)
  756.     SYM            *sp;
  757.     int             offset;
  758. {
  759.     char            sign;
  760.  
  761.     if (sp == NULL) {
  762.         fprintf( stderr, "DIAG -- NULL argument to genref.\n" );
  763.         return;
  764.     }
  765.     if (offset >= 0) 
  766.         sign = '+';
  767.     else {
  768.         sign = '-';
  769.         offset = -offset;
  770.     }
  771.  
  772.     if (gentype == longgen && outcol < 55 - strlen(sp->name)) {
  773.         if (sp->storage_class == sc_static) {
  774.             fprintf( output, ",L%d", sp->value.i );
  775.             if (offset != 0) {
  776.                 fprintf( output, "%c%d", sign, offset );
  777.             }
  778.         }
  779.         else {
  780.             fprintf( output, ",_%s", sp->name );
  781.             if (offset != 0) {
  782.                 fprintf( output, "%c%d", sign, offset );
  783.             }
  784.         }
  785.         outcol += (11 + strlen(sp->name));
  786.     }
  787.     else {
  788.         nl();
  789.         if (sp->storage_class == sc_static) {
  790.             fprintf( output, "\tDC.l\tL%d", sp->value.i );
  791.             if (offset != 0) {
  792.                 fprintf( output, "%c%d", sign, offset );
  793.             }
  794.         }
  795.         else {
  796.             fprintf( output, "\tDC.l\t_%s", sp->name );
  797.             if (offset != 0) {
  798.                 fprintf( output, "%c%d", sign, offset );
  799.             }
  800.         }
  801.         outcol = 26 + strlen(sp->name);
  802.         gentype = longgen;
  803.     }
  804. }
  805.  
  806. int
  807. genalignment(align)
  808.     int             align;
  809. {
  810.     nl();
  811.     switch (align) {
  812.     case 0:
  813.     case 1:
  814.         break;
  815.     case 2:
  816.     case 4:
  817.     case 8:
  818.         fprintf( output, "\tCNOP\t0,%d\n", align);
  819.         break;
  820.     default:
  821.         fprintf( stderr, "DIAG -- invalid alignment\n" );
  822.         break;
  823.     }
  824.     return (align);
  825. }
  826.  
  827. void
  828. genstorage(nbytes)
  829.     int             nbytes;
  830. {
  831.     nl();
  832.     fprintf( output, "\tDS.b\t%d\n", nbytes );
  833. }
  834.  
  835. void
  836. gen_labref(n, offset)
  837.     int             n;
  838.     int             offset;
  839. {
  840.     if (gentype == longgen && outcol < 58) {
  841.         fprintf( output, ",L%d", n );
  842.         if (offset != 0) {
  843.             fprintf( output, "%c%d", (offset > 0) ? '+' : '-', offset );
  844.         }
  845.         outcol += 6;
  846.     }
  847.     else {
  848.         nl();
  849.         fprintf( output, "\tDC.l\tL%d", n );
  850.         if (offset != 0) {
  851.             fprintf( output, "%c%d", (offset > 0) ? '+' : '-', offset );
  852.         }
  853.         outcol = 22;
  854.         gentype = longgen;
  855.     }
  856. }
  857.  
  858. /*
  859.  * stringconcat
  860.  *
  861.  * Adds the string s onto the end of a string literal selected by index (the
  862.  * label of the string being appended.
  863.  *
  864.  * Returns index if successful, 0 if failed.
  865.  */
  866.  
  867. long
  868. stringconcat(index, s)
  869.     int             index;
  870.     char           *s;
  871. {
  872.     char           *buf;
  873.     int             length;
  874.     struct slit    *lp;
  875.  
  876.     if (s == NULL) {
  877.         fprintf( stderr, "DIAG -- NULL argument to stringconcat.\n" );
  878.         return (0);
  879.     }
  880.  
  881.     for (lp = strtab; lp != NULL; lp = lp->next)
  882.         if (lp->label == index)
  883.             break;
  884.  
  885.     if (lp != NULL) {
  886.         length = strlen(s);
  887.         ++global_flag;  /* Allocate from the global space   */
  888.         buf = (char *) xalloc(lp->len + length + 1);
  889.         bcopy(lp->str, buf, lp->len);
  890.         lp->str = buf;
  891.         buf += lp->len;
  892.         bcopy(s, buf, length + 1);
  893.         lp->len += length;
  894.         --global_flag;
  895.         return (index);
  896.     }
  897.     return (0);
  898. }
  899.  
  900. /*
  901.  * stringlit
  902.  *
  903.  * Make s a string literal and return the label number under which it will be
  904.  * output.
  905.  */
  906.  
  907. long
  908. stringlit(s)
  909.     char           *s;
  910. {
  911.     struct slit    *lp;
  912.  
  913.     if (s == NULL) {
  914.         fprintf( stderr, "DIAG -- NULL argument to stringlit.\n" );
  915.         return (0);
  916.     }
  917.     ++global_flag;      /* always allocate from global space. */
  918.     lp = (struct slit *) xalloc(sizeof(struct slit));
  919.     lp->label = nextlabel++;
  920.     lp->str = litlate(s);
  921.     lp->len = strlen(s);
  922.     lp->type = sconst;
  923.     lp->next = strtab;
  924.     strtab = lp;
  925.     --global_flag;
  926.     return lp->label;
  927. }
  928.  
  929. /*
  930.  * floatlit
  931.  *
  932.  * Make d a double-precision floating point literal and return the label number
  933.  * under which it will be output.  Hacked to share the slit structure, but uses
  934.  * rconst to distiguish it from an sconst.
  935.  */
  936.  
  937. long
  938. floatlit(d)
  939.     double          d;
  940. {
  941.     double         *dptr;
  942.     struct slit    *lp;
  943.  
  944.     ++global_flag;      /* always allocate from global space. */
  945.     lp = (struct slit *) xalloc(sizeof(struct slit));
  946.     lp->label = nextlabel++;
  947.     lp->str = (char *) xalloc(sizeof(double));
  948.     lp->len = sizeof(double);
  949.     lp->next = strtab;
  950.     lp->type = rconst;
  951.     strtab = lp;
  952.     --global_flag;
  953.     dptr = (double *) lp->str;
  954.     *dptr = d;
  955.     return lp->label;
  956. }
  957.  
  958. /* 
  959.  * getlit
  960.  *
  961.  * Locates a literal by its index and return a pointer to the object.
  962.  */
  963.  
  964. void *
  965. getlit(num)
  966.     int             num;
  967. {
  968.     struct slit    *lp;
  969.     void           *ptr;
  970.  
  971.     if (strtab != NULL) {
  972.         lp = strtab;
  973.         for (lp = strtab; lp != NULL; lp = lp->next) {
  974.             if (lp->label == num) {
  975.                 ptr = (void *) lp->str;
  976.                 return (ptr);
  977.             }
  978.         }
  979.     }
  980.     return (NULL);
  981. }
  982.  
  983. /*
  984.  * remlit
  985.  *
  986.  * Accepts a label and removes from the list all associated slits.
  987.  * Returning a pointer to the string or NULL if the label wasn't found.
  988.  */
  989.  
  990. void *
  991. remlit(num)
  992.     int             num;
  993. {
  994.     struct slit    *lp, **last;
  995.     void           *ptr;
  996.  
  997.     if (strtab != NULL) {
  998.         lp = strtab;
  999.         last = &strtab;
  1000.         while (lp != NULL) {
  1001.             if (lp->label == num) {
  1002.                 *last = lp->next;
  1003.                 ptr = (void *) lp->str;
  1004.                 return (ptr);
  1005.             }
  1006.             last = &lp->next;
  1007.             lp = lp->next;
  1008.         }
  1009.     }
  1010.     return (NULL);
  1011. }
  1012.  
  1013. /*
  1014.  * Dumps the string literal pool.
  1015.  */
  1016.  
  1017. void
  1018. dumplits()
  1019. {
  1020.     char           *cp;
  1021.     int             i, count;
  1022.  
  1023.     while (strtab != NULL) {
  1024.         cseg();
  1025.         nl();
  1026.         put_label( strtab->label );
  1027.         cp = strtab->str;
  1028.         count = strtab->len;
  1029.         for (i = 0; i < strtab->len; i++) {
  1030.             genbyte(*cp++);
  1031.         }
  1032.         if (strtab->type == sconst) {
  1033.             ++count;
  1034.             genbyte(0);
  1035.         }
  1036.         if ((count % 2) != 0) {
  1037.             genbyte(0);
  1038.         }
  1039.         strtab = strtab->next;
  1040.     }
  1041.     nl();
  1042. }
  1043.  
  1044. /*
  1045.  * nl
  1046.  *
  1047.  * Generates a newline if needed.
  1048.  */
  1049.  
  1050. void
  1051. nl()
  1052. {
  1053.     if (outcol > 0) {
  1054.         fprintf( output, "\n" );
  1055.         outcol = 0;
  1056.         gentype = nogen;
  1057.     }
  1058. }
  1059.  
  1060. /*
  1061.  * cseg
  1062.  *
  1063.  * Directs output to the code segment.
  1064.  */
  1065.  
  1066. void
  1067. cseg()
  1068. {
  1069.     if (curseg != codeseg) {
  1070.         nl();
  1071.         fprintf( output, "\tSECTION\t%s,CODE\n", code_name );
  1072.         curseg = codeseg;
  1073.     }
  1074. }
  1075.  
  1076. /*
  1077.  * dseg
  1078.  *
  1079.  * Directs output to the DATA segment.
  1080.  */
  1081.  
  1082. void
  1083. dseg()
  1084. {
  1085.     if (curseg != dataseg) {
  1086.         nl();
  1087.         fprintf( output, "\tSECTION\t%s,DATA\n", data_name );
  1088.         curseg = dataseg;
  1089.     }
  1090. }
  1091.  
  1092. /*
  1093.  * bseg
  1094.  *
  1095.  * Directs output to the BSS (unitialized data) segment.
  1096.  */
  1097.  
  1098. void
  1099. bseg()
  1100. {
  1101.     if (curseg != bssseg) {
  1102.         nl();
  1103.         fprintf( output, "\tSECTION\t%s,BSS\n", bss_name );
  1104.         curseg = bssseg;
  1105.     }
  1106.  
  1107. }
  1108.